home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 751-760 / 751 / yearprintq / src / yearprintq2_5.c < prev   
C/C++ Source or Header  |  1995-03-18  |  53KB  |  1,821 lines

  1. /*****************************************************************************\
  2.  * $VER: YearPrintQ.c 2.5    DICE/LATTICE C/SAS C/AZTEC C + AmigaOS 2.04/2.1 *
  3.  *                 _                                                         *
  4.  *            _   // (c)1992 by "Quarky" Dieter Temme                        *
  5.  *            \\ //                                                          *
  6.  * :ts=4       \X/ --- Freeware --- ONLY AMIGA MAKES IT POSSIBLE             *
  7.  *                                                                           *
  8.  * produces a printout of one fourth of a calendar on a sheet of paper sized *
  9.  * DIN A5                                                                    *
  10. \*****************************************************************************/
  11.  
  12. #define PRGNAME "YearPrintQ"
  13. #define VERSION "2.5"
  14. #define PRGDATE "13.9.92"
  15.  
  16. #include "amigacompq.h"
  17.  
  18. #include <ctype.h>
  19. #include <stdarg.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <exec/types.h>
  23. #include <clib/asl_protos.h>
  24. #include <clib/dos_protos.h>
  25. #include <clib/exec_protos.h>
  26. #include <clib/gadtools_protos.h>
  27. #include <clib/graphics_protos.h>
  28. #include <clib/icon_protos.h>
  29. #include <clib/intuition_protos.h>
  30. #include <clib/locale_protos.h>
  31. #include <clib/utility_protos.h>
  32. #include <clib/wb_protos.h>
  33. #include <devices/printer.h>
  34. #include <dos/dos.h>
  35. #include <exec/execbase.h>
  36. #include <exec/io.h>
  37. #include <exec/memory.h>
  38. #include <graphics/text.h>
  39. #include <intuition/intuition.h>
  40. #include <intuition/gadgetclass.h>
  41. #include <libraries/asl.h>
  42. #include <libraries/gadtools.h>
  43. #include <libraries/locale.h>
  44. #include <utility/date.h>
  45. #include <workbench/startup.h>
  46. #include <workbench/workbench.h>
  47.  
  48. #ifdef PRAGMAS_
  49.  #include <pragmas/asl_lib.h>
  50.  #include <pragmas/dos_lib.h>
  51.  #include <pragmas/exec_lib.h>
  52.  #include <pragmas/gadtools_lib.h>
  53.  #include <pragmas/graphics_lib.h>
  54.  #include <pragmas/icon_lib.h>
  55.  #include <pragmas/intuition_lib.h>
  56.  #include <pragmas/locale_lib.h>
  57.  #include <pragmas/utility_lib.h>
  58.  #include <pragmas/wb_lib.h>
  59. #endif
  60.  
  61. #ifdef LATTICE
  62.  int CXBRK(void) { return 0; }  /* Disable Lattice CTRL-C handling */
  63.  int chkabort(void) { return 0; }
  64. #endif
  65.  
  66. #ifdef AZTEC_C
  67.  void _wb_parse(void) { extern long Enable_Abort; Enable_Abort= FALSE; }
  68.  void _cli_parse(void) { extern long _argc; _argc= ~0; }
  69.  void _abort(void) {}
  70. #endif
  71.  
  72. /*>> version <<*/
  73. TEXT Version[]= "\0$VER: " PRGNAME " " VERSION " (" PRGDATE ")";
  74.  
  75. /*>> English display output strings and constants <<*/
  76. #define STRINGARRAY
  77. #include "YearPrintQ.h"
  78.  
  79. /*>> library bases and locale/catalog variables <<*/
  80. extern struct Library *SysBase;
  81. struct Library *AslBase, *GadToolsBase, *GfxBase, *IconBase, *IntuitionBase,
  82.                *LocaleBase, *UtilityBase, *WorkbenchBase;
  83. struct Locale *locale;
  84. struct Catalog *cat;
  85.  
  86. /*>> constants <<*/
  87. #define NUMDAYS         31        /* number of days in months */
  88. #define NUMMONTHS     12        /* number of months */
  89. #define NUMWEEKDAYS     7        /* number of weekdays */
  90. #define MAXWIDTH     26        /* maximum length of holiday name */
  91. #define DEFCOUNTING     TRUE    /* default for week numbering */
  92. #define DEFRESTWDAY     0        /* default for weekly rest-day */
  93. #define DEFFIRSTWDAY 1        /* default for first weekday in a week */
  94. #define DEFQUART     4        /* default for quarter */
  95. #define DEFGRAPH     TRUE    /* default for graphics */
  96. #define DEFPITCH     3        /* default for pitch */
  97.  
  98. /*>> main variables <<*/
  99. BOOL cli;                    /* TRUE if running in CLI */
  100. BPTR lock= ~0;                /* contains original CurrentDir() */
  101. ULONG year;                    /* year to print */
  102. BOOL fileflag;                /* TRUE if file was read */
  103.  
  104. /*>> GUI variables <<*/
  105. TEXT *name;                    /* contains last filename */
  106. ULONG signals;                /* signals to wait for */
  107. APTR vi;                    /* Intuition's visual information structure */
  108. struct Screen *pubscr;        /* pointer to public screen */
  109. struct Window *win;            /* pointer to YearPrintQ's window */
  110. struct MsgPort *appport;    /* message port for Workbench application window */
  111. struct AppWindow *appwin;    /* Workbench's application window structure */
  112. struct Gadget *congad;        /* pointer to GadTool's anchor gagdet structure */
  113. struct FileRequester *freq;    /* pointer to ASL file requester structure */
  114.  
  115. /*>> printer device variables <<*/
  116. struct MsgPort *prtport;    /* message port for printer device */
  117. struct IOStdReq *prtreq;    /* Printer's device request structure */
  118.  
  119. /*>> national calendar variables <<*/
  120. UBYTE counting= DEFCOUNTING; /* TRUE if week numbering is requested */
  121. UBYTE firstwday= DEFFIRSTWDAY; /* weekday number of first weekday in a week */
  122. UBYTE restwday= DEFRESTWDAY; /* weekday number of weekly rest-day */
  123.  
  124. /*>> calendar variables (for current year) <<*/
  125. BYTE firstday[NUMMONTHS];    /* first weekday of each month */
  126. BYTE firstweek[NUMMONTHS];    /* no. of first week of each month */
  127. UBYTE days[NUMMONTHS]=        /* number of days in the months */
  128. {    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  129. };
  130.  
  131. /*>> structure for saving the holidays read from file <<*/
  132. struct fileday
  133. {    struct fileday *next;    /* pointer to next structure, else NULL */
  134.     TEXT name[MAXWIDTH];    /* name of holiday */
  135.     UBYTE month;            /* month of holiday */
  136.     UBYTE day;                /* day of holiday or weekday number */
  137.     WORD offset;            /* offset of holiday */
  138.     BOOL flags;                /* see below */
  139. } *filedays;                /* pointing to holidays or NULL */
  140.  
  141. /*>> structure sorted for printing <<*/
  142. struct yearday
  143. {    struct yearday *next;    /* pointer to next structure, else NULL */
  144.     TEXT *name;                /* pointer to name in struct fileday */
  145.     UBYTE day;                /* day of holiday in requested year */
  146.     BOOL flags;                /* flag FREEDAY set or cleared */
  147. } *yeardays[NUMMONTHS];        /* pointing to holidays in month or NULL */
  148.  
  149. /*>> flags <<*/
  150. #define FIRSTWDAY    0x01    /* first weekday requested (number in .day) */
  151. #define LASTWDAY    0x02    /* last weekday requested (number in .day) */
  152. #define EASTER        0x04    /* offset from Easter Sunday */
  153. #define ADVENT        0x08    /* offset from Advent Sunday */
  154. #define FREEDAY        0x10    /* flag for a rest-day */
  155. #define ALLOCATED    0x20    /* memory for name in yeardays was allocated */
  156.  
  157. /*>> names for weeks and months <<*/
  158. BOOL wdflag;                /* TRUE if weekdays read from file */
  159. TEXT *weekdays[NUMWEEKDAYS]; /* names of weekdays */
  160. BOOL mnflag;                /* TRUE if month names read from file */
  161. TEXT *months[NUMMONTHS];    /* names of months */
  162.  
  163. /*>> file requester gadget image <<*/
  164. UWORD fridata[]=            /* must be copied into ChipMem */
  165. {    0xFFF8, 0xE0DC, 0xE0DC, 0xE01C, 0xFFFC,
  166.     0xFFFC, 0xFFFC, 0xFFFC, 0xFFFC, 0xFFFC,
  167.     0x0000, 0x7FF0, 0x7FF8, 0x7FF8, 0x7FF8,
  168.     0x7FF8, 0x7FF8, 0x5FF8, 0x7FF8, 0x0000
  169. };
  170. struct Image frimage=
  171. {    3, 2, 14, 10, 2, fridata, 0x0003, 0x0000, NULL
  172. };
  173.  
  174. /*>> busy mouse pointer image <<*/
  175. UWORD *pimage;                /* mouse imagedata in chip mem */
  176. UWORD mouseimage[]=            /* a 'simple sprite' */
  177. {    0, 0,
  178.     0x0400, 0x07c0, 0x0000, 0x07c0, 0x0100, 0x0380, 0x0000, 0x07e0,
  179.     0x07c0, 0x1ff8, 0x1ff0, 0x3fec, 0x3ff8, 0x7fde, 0x3ff8, 0x7fbe,
  180.     0x7ffc, 0xff7f, 0x7efc, 0xffff, 0x7ffc, 0xffff, 0x3ff8, 0x7ffe,
  181.     0x3ff8, 0x7ffe, 0x1ff0, 0x3ffc, 0x07c0, 0x1ff8, 0x0000, 0x07e0,
  182.     0, 0
  183. };
  184.  
  185. /*>> definitions for gadgets <<*/
  186. #define GID_QUART        0
  187. #define GID_YEAR        1
  188. #define GID_FREQ        2
  189. #define GID_FILE        3
  190. #define GID_PITCH        4
  191. #define GID_GRAPH        5
  192. #define GID_PRINT        6
  193. #define GID_STOP        7
  194.  
  195. /*>> structure for gadgets <<*/
  196. #define LEFT_    0         /* at left window border for BUTTON_KIND,
  197.                               directly after text else */
  198. #define RIGHT_    128         /* at right window border */
  199. struct
  200. {    BYTE line;                 /* line in display to appear, last item: -1 */
  201.     UBYTE left;                 /* PLACE_LEFT_ or PLACE_RIGHT_ plus offset */
  202.     BYTE textnum;             /* number of localized text string */
  203.     ULONG kind;                 /* parameter for CreateGadget() (and ng_Flags),
  204.                                 IMAGE_KIND_ with internal processing */
  205.     UWORD width;             /* INTEGER_KIND/STRING_KIND/GENERIC_KIND:
  206.                                 number of chars, CYCLE_KIND: string array
  207.                                 is scanned (where &array is second tag in
  208.                                 taglist).
  209.                                 ATTENTION: is changed for calculation! */
  210.     UBYTE contents;             /* actual number for CYCLE_KIND gadgets */
  211.     ULONG misc;                 /* GTST_STRING, GTIN_Number, GTCY_LABELS */
  212.     struct Gadget *gad;         /* NULL, later result of CreateGadget() */
  213. } gads[]=
  214. {    {    0, LEFT_,    MSG_QUART_GADTXT, CYCLE_KIND, 0, DEFQUART    },
  215.     {    1, LEFT_,    MSG_YEAR_GADTXT,  INTEGER_KIND, 5            },
  216.     {    2, LEFT_,    -1,                  GENERIC_KIND, 1,            },
  217.     {    2, LEFT_+1,    MSG_FILE_GADTXT,  STRING_KIND, 20,            },
  218.     {    3, LEFT_,    MSG_PITCH_GADTXT, CYCLE_KIND, 0, DEFPITCH    },
  219.     {    4, LEFT_,    MSG_GRAPH_GADTXT, CYCLE_KIND, 0, DEFGRAPH    },
  220.     {    5, LEFT_,    MSG_PRINT_GAD,      BUTTON_KIND, 0            },
  221.     {    5, RIGHT_,    MSG_STOP_GAD,      BUTTON_KIND, 0            },
  222.     {    -1                                                        }
  223. };
  224.  
  225. /*==== get string from locale/catalog ====*/
  226. TEXT *GetLocaleStrQ_(UBYTE num)
  227. {    static TEXT *orig_weekdays[NUMWEEKDAYS]=
  228.     {    "Mo", "Tu", "We", "Th", "Fr", "Sa", "So"
  229.     };
  230.     static TEXT *orig_months[NUMMONTHS]=
  231.     {    "January", "February", "March", "April", "May", "June",
  232.         "July", "August", "September", "October", "November", "December"
  233.     };
  234.     static TEXT *orig_abmonths[NUMMONTHS]=
  235.     {    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  236.         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  237.     };
  238.  
  239.     if (!LocaleBase && (num >= ABMON_1))
  240.         return orig_abmonths[num-ABMON_1];
  241.     if ((!LocaleBase || mnflag) && (num >= MON_1))
  242.         return (mnflag? months : orig_months)[num-MON_1];
  243.     if ((!LocaleBase || wdflag) && (num >= ABDAY_1))
  244.         return (wdflag? weekdays : orig_weekdays)[num-ABDAY_1];
  245.     return GetLocaleStr(locale, (ULONG)num);
  246. }
  247. TEXT *GetCatalogStrQ_(BYTE num)
  248. {    if (num < 0) return "";
  249.     return LocaleBase? GetCatalogStr(cat, num, AppStrings[num].as_Str)
  250.         : AppStrings[num].as_Str;
  251. }
  252.  
  253. /*==== bring error text to the user ====*/
  254. #define ERR_RETRY_    1    /* bit flags for the requested gadgets to choose */
  255. #define ERR_ABORT_    2
  256. #define ERR_CONTI_    4
  257. #define ERR_QUIT_    8
  258. UBYTE PrintError_(const UBYTE mode, TEXT *str, ...)
  259. {    static struct EasyStruct easystruct=
  260.     {    sizeof(struct EasyStruct), 0, NULL, NULL, NULL
  261.     };
  262.  
  263.     if (cli)
  264.     {    UWORD i= 0;
  265.         TEXT buf[256];
  266.         va_list ap;
  267.         va_start(ap, str);
  268.  
  269.         sprintf(buf, PRGNAME ": %s\n", str);
  270.         do
  271.         {    if (buf[i] == '\n') buf[i]= ' ';
  272.         } while (buf[i++]);
  273.         buf[i-2]= '\n';
  274.  
  275.         VPrintf(buf, &va_arg(ap, LONG));
  276.         va_end(ap);
  277.         return FALSE;
  278.     } else if (IntuitionBase)
  279.     {    TEXT buf[4*30];
  280.         UBYTE i;
  281.         ULONG idcmpflags;
  282.         va_list ap;
  283.  
  284.         buf[0]= '\0';
  285. #define SETBUF(x, y) if (mode&(x)) strcat(strcat(buf, "|"), GetCatalogStrQ_(y))
  286.         SETBUF(ERR_RETRY_, MSG_RETRY_GAD);
  287.         SETBUF(ERR_QUIT_, MSG_QUIT_GAD);
  288.         SETBUF(ERR_CONTI_, MSG_CONTI_GAD);
  289.         SETBUF(ERR_ABORT_, MSG_ABORT_GAD);
  290. #undef SETBUF
  291.         easystruct.es_TextFormat= str;
  292.         easystruct.es_GadgetFormat= buf+1;
  293.         DisplayBeep(pubscr);
  294.         va_start(ap, str);
  295.         if (pimage && win)
  296.         {    idcmpflags= win->IDCMPFlags;
  297.             ModifyIDCMP(win, IDCMP_MENUPICK);
  298.             SetPointer(win, pimage, 16, 16, -6, 0);
  299.         }
  300.         i= (UBYTE)EasyRequestArgs(win, &easystruct, NULL, &va_arg(ap, TEXT *));
  301.         if (pimage && win)
  302.         {    ClearPointer(win);
  303.             ModifyIDCMP(win, idcmpflags);
  304.         }
  305.         va_end(ap);
  306.         return i;
  307.     } else
  308.         return FALSE;
  309. }
  310.  
  311. /*==== open library ====*/
  312. struct Library *OpenLibraryQ_(TEXT *str)
  313. {    struct Library *base;
  314.  
  315.     while (!(base= OpenLibrary(str, 36)))
  316.         if (!PrintError_(ERR_QUIT_, GetCatalogStrQ_(MSG_NOTFOUND),
  317.             GetCatalogStrQ_(MSG_LIBRARY), str))
  318.             exit(RETURN_FAIL);
  319.     return base;
  320. }
  321.  
  322. /*==== allocate memory ====*/
  323. void *MAllocQ_(const ULONG size)
  324. {    void *ptr;
  325.  
  326.     while (!(ptr= malloc(size)))
  327.         if (!PrintError_(ERR_RETRY_|ERR_QUIT_, GetCatalogStrQ_(MSG_NOMEMORY)))
  328.             exit(RETURN_FAIL);
  329.  
  330.     return ptr;
  331. }
  332.  
  333. /*==== get character for "keyable" gagdets ====*/
  334. TEXT GetGadgetChar_(BYTE num)
  335. {    TEXT *s= strchr((num < 0)? "" : GetCatalogStrQ_(num), '_');
  336.     return s? ToUpper(s[1]) : '\0';
  337. }
  338.  
  339. /*==== resize an imagedata field ====*/
  340. BOOL ResizeImage_(struct Image *image, UWORD newx, UWORD newy)
  341. {    BYTE oldflag, newflag;
  342.     WORD cntx, cnty;
  343.     UWORD x,y, depth, *newindex, *copyindex, newwidth= (newx+15)>>4;
  344.     UWORD *oldindex= image->ImageData;
  345.  
  346.     x= image->PlanePick; depth= 0;
  347.     while (x)
  348.     {    depth++;
  349.         do x>>= 1; while (x && !(x&1));
  350.     }
  351.     x= (depth*newy*newwidth<<1)+2;
  352.  
  353.     while (!(newindex= (UWORD *)AllocMem(x, MEMF_CHIP)))
  354.         if (!(PrintError_(ERR_RETRY_|ERR_ABORT_,
  355.             GetCatalogStrQ_(MSG_NOMEMORY))))
  356.             return FALSE;
  357.  
  358.     newindex[0]= x;
  359.     image->ImageData= ++newindex;
  360.  
  361.     while (depth--)
  362.     {    cnty= image->Height; y= newy;
  363.         do
  364.         {    if ((cnty-= image->Height) > 0)
  365.             {    CopyMem(copyindex, newindex, newwidth<<1);
  366.                 newindex+= newwidth;
  367.             } else
  368.             {    cnty+= newy;
  369.                 oldflag= newflag= 15;
  370.                 copyindex= newindex;
  371.                 cntx= image->Width; x= newx;
  372.                 do
  373.                 {    if (newflag == 15) *newindex= 0;
  374.                     if (*oldindex&(1<<oldflag)) *newindex|= 1<<newflag;
  375.                     if ((cntx-= image->Width) <= 0)
  376.                     {    cntx+= newx;
  377.                         if (--oldflag < 0) { oldflag= 15; oldindex++; }
  378.                     }
  379.                     if (--newflag < 0) { newflag= 15; newindex++; }
  380.                 } while (--x > 0);
  381.                 if (oldflag != 15) oldindex++;
  382.                 if (newflag != 15) newindex++;
  383.             }
  384.         } while (--y > 0);
  385.     }
  386.  
  387.     image->Width= newx;
  388.     image->Height= newy;
  389.     return TRUE;
  390. }
  391.  
  392. /*==== calculate holidays for given year ====*/
  393. BOOL CalcYear_(BOOL new, LONG newyear)
  394. {    /*- year shall be considered of current year plus one -*/
  395.     if (new && !year)
  396.     {    ULONG secs, micros;
  397.         struct ClockData clockdata;
  398.  
  399.         CurrentTime(&secs, µs);
  400.         Amiga2Date(secs, &clockdata);
  401.         newyear= clockdata.year+1;
  402.     }
  403.  
  404.     /*- number of year not right? -*/
  405.     if ((newyear < 1582) || (newyear > 2199)) return FALSE;
  406.  
  407.     if (win)
  408.         GT_SetGadgetAttrs(gads[GID_YEAR].gad, win, NULL,
  409.             GTIN_Number, newyear,
  410.             TAG_DONE);
  411.  
  412.     /*- calculate all dependencies -*/
  413.     {    BYTE adventday;            /* number of day of Easter Sunday */
  414.         BYTE easterday;            /* number of day of 1st Advent */
  415.         UBYTE month;            /* loop variable */
  416.         BOOL leapyear;            /* TRUE if year is leapyear */
  417.  
  418.         year= newyear;
  419.  
  420.         /* calculate if year is leapyear */
  421.         leapyear= !(year%4) && (year%100 || !(year%400));
  422.         days[1]= 28+leapyear;
  423.  
  424.         /* calculate first day and no. of week of every month */
  425.         firstday[0]= (year-1+(year-1)/4-(year-1)/100+(year-1)/400)%NUMWEEKDAYS;
  426.         firstweek[0]=
  427.             (NUMWEEKDAYS+firstday[0]-firstwday)%NUMWEEKDAYS < NUMWEEKDAYS/2;
  428.         for (month= 1; month < NUMMONTHS; month++)
  429.         {    firstweek[month]= firstweek[month-1]+
  430.                 (firstday[month-1]+days[month-1])/NUMWEEKDAYS;
  431.             firstday[month]= (firstday[month-1]+days[month-1])%NUMWEEKDAYS;
  432.         }
  433.  
  434.         /* calculate date of Easter */
  435.         {    UWORD S, A, D, E;    /* temporary variables (excellent music ;-) */
  436.  
  437.             S= year/100;
  438.             A= year%19;
  439.             D= A*19+22; if (S > 16) D++; if (S > 18) D++; D= D%30;
  440.             E= 6;
  441.             if (S < 21) E--; if (S < 19) E--;
  442.             if (S < 18) E--; if (S < 17) E--;
  443.             E= (2*(year%4)+4*(year%7)+6*D+E)%7;
  444.             easterday= D+E+22;
  445.             if (easterday == 57) easterday-= 7;
  446.             if ((easterday == 56) && (D == 28) && (A > 10)) easterday= 35;
  447.         }
  448.  
  449.         /* calculate date of 1st Advent */
  450.         adventday= -(firstday[0]+5)%7-leapyear;
  451.         if (adventday <= -4) adventday+= 7;
  452.  
  453.         /* delete yeardays from memory */
  454.         {    struct yearday *point, *old;
  455.  
  456.             for (month= 0; month < NUMMONTHS; month++)
  457.             {    point= yeardays[month];
  458.                 while (point)
  459.                 {    old= point->next;
  460.                     if (point->flags&ALLOCATED) free(point->name);
  461.                     free(point);
  462.                     point= old;
  463.                 }
  464.                 yeardays[month]= NULL;
  465.             }
  466.         }
  467.         
  468.         /* calculate dates in yeardays[] */
  469.         if (fileflag)
  470.         {    WORD day;
  471.             struct fileday *filepoint;
  472.             struct yearday *yearpoint, *old;
  473.  
  474.             filepoint= filedays;
  475.             while (filepoint)
  476.             {    if (filepoint->flags&EASTER)
  477.                 {    month= 3-1;
  478.                     day= easterday;
  479.                 } else if (filepoint->flags&ADVENT)
  480.                 {    month= 12-1;
  481.                     day= adventday;
  482.                 } else if (filepoint->flags&(FIRSTWDAY|LASTWDAY))
  483.                 {    month= filepoint->month;
  484.                     day= filepoint->day-firstday[month];
  485.                     if (day <= 0) day+= NUMWEEKDAYS;
  486.  
  487.                     if (filepoint->flags&LASTWDAY)
  488.                     {    day= day+days[month]-days[month]%NUMWEEKDAYS;
  489.                         if (day > days[month]) day-= NUMWEEKDAYS;
  490.                     }
  491.                 } else
  492.                 {    month= filepoint->month;
  493.                     day= filepoint->day;
  494.                 }
  495.  
  496.                 day+= filepoint->offset;
  497.  
  498.                 while ((day <= 0) && (month > 0))
  499.                     day+= days[--month];
  500.                 while ((day > days[month]) && (month < NUMMONTHS))
  501.                     day-= days[month++];
  502.  
  503.                 if (month < NUMMONTHS)
  504.                 {    old= NULL;
  505.                     yearpoint= yeardays[month];
  506.                     if ((month == 1) && (day > days[1])) day--; /* leapyear */
  507.                     while (yearpoint && ((UBYTE)day > yearpoint->day))
  508.                     {    old= yearpoint;
  509.                         yearpoint= yearpoint->next;
  510.                     }
  511.  
  512.                     if (yearpoint && ((UBYTE)day == yearpoint->day))
  513.                     {    UBYTE i;
  514.  
  515.                         if ((i= strlen(yearpoint->name)) < MAXWIDTH-3)
  516.                         {    TEXT *str;
  517.  
  518.                             if (!(yearpoint->flags&ALLOCATED))
  519.                             {    str= MAllocQ_(MAXWIDTH);
  520.                                 strcpy(str, yearpoint->name);
  521.                                 yearpoint->flags|= ALLOCATED;
  522.                             } else
  523.                                 str= yearpoint->name;
  524.                             strcat(str+i, ", ");
  525.                             strncpy(str+i+2, filepoint->name, MAXWIDTH-3-i);
  526.                             str[MAXWIDTH-1]= '\0';
  527.                             yearpoint->name= str;
  528.                             yearpoint->flags|= filepoint->flags&FREEDAY;
  529.                         }
  530.                     } else
  531.                     {    struct yearday *newday;
  532.  
  533.                         newday= (struct yearday *)
  534.                             MAllocQ_(sizeof(struct yearday));
  535.  
  536.                         newday->name= filepoint->name;
  537.                         newday->flags= filepoint->flags&FREEDAY;
  538.                         newday->day= day;
  539.  
  540.                         if (!old)    yeardays[month]= newday;
  541.                         else        old->next= newday;
  542.                         newday->next= yearpoint;
  543.                     }
  544.                 }
  545.  
  546.                 filepoint= filepoint->next;
  547.             }
  548.         }
  549.     }
  550.     return TRUE;
  551. }
  552.  
  553. /*==== read holiday file ====*/
  554. #define SECT_INCLD    0
  555. #define SECT_MNAMS    1
  556. #define SECT_WDAYS    2
  557. #define SECT_WKCNT    3
  558. #define SECT_FWDAY    4
  559. #define SECT_RWDAY    5
  560. #define SECT_HDAYS    6
  561. BOOL ReadFile_(TEXT *filename)
  562. {    UBYTE count;                /* number of item in section, for limiting */
  563.     UBYTE num;                    /* number of error specification string */
  564.     BYTE section= -1;            /* descriptor of section actually read */
  565.     struct fileday *newday;        /* pointer to new newday structure */
  566.     UWORD day, month, end;        /* temporary variables */
  567.     TEXT buf[256], *str, *s;    /* temporary variables */
  568.     BPTR fh;                    /* file descriptor for defaults file */
  569.     BOOL forward;                /* TRUE if new include file to scan */
  570.  
  571.     /*- file structure for subsequent #INCLUDE's -*/
  572.     struct file
  573.     {    struct files *prev;        /* linked list of file structs */
  574.         TEXT *name;                /* pointer to filename (mallocated) */
  575.         LONG pos;                /* current position in file for Seek() */
  576.         UWORD line;                /* current line in file */
  577.     } *current;
  578.  
  579.     /*- sections' names and counts array -*/
  580.     TEXT *sectnames[]=
  581.     {    "INCLUDE", "MONTHNAMES", "WEEKDAYS", "WEEKCOUNT",
  582.         "FIRSTWDAY", "RESTWDAY", "HOLIDAYS", NULL
  583.     };
  584.     TEXT sectcounts[]=
  585.     {    1, NUMMONTHS, NUMWEEKDAYS, 1, 1, 1, 0
  586.     };
  587.  
  588.     /*- set filename in file gadget -*/
  589.     if (win)
  590.         GT_SetGadgetAttrs(gads[GID_FILE].gad, win, NULL,
  591.             GTST_String, (ULONG)name,
  592.             TAG_DONE);
  593.  
  594.     /*- initialize variables -*/
  595.     wdflag= mnflag= FALSE;
  596.     counting= DEFCOUNTING;
  597.     restwday= DEFRESTWDAY;
  598.     firstwday= locale? locale->loc_CalendarType : DEFFIRSTWDAY;
  599.     for (month= 0; month < NUMMONTHS; month++)
  600.         if (months[month]) free(months[month]);
  601.     for (num= 0; num < NUMWEEKDAYS; num++)
  602.         if (weekdays[num]) free(weekdays[num]);
  603.  
  604.     /*- delete filedays from memory -*/
  605.     {    struct fileday *old;
  606.  
  607.         while (filedays)
  608.         {    old= filedays->next;
  609.             free(filedays);
  610.             filedays= old;
  611.         }
  612.     }
  613.  
  614.     /*- fill first file structure -*/
  615.     if (!filename) filename= "";
  616.     current= (struct file *)MAllocQ_(sizeof(struct file));
  617.     current->prev= NULL;
  618.     current->name= strcpy((TEXT *)MAllocQ_(strlen(filename)+1), filename);
  619.     forward= TRUE;
  620.  
  621.     for (;;)
  622.     {    /* get next file */
  623.         if (!forward)
  624.         {    struct file *old= current->prev;
  625.             free(current->name);
  626.             free(current);
  627.             current= old;
  628.             section= SECT_INCLD;
  629.             count= 1;
  630.         } else
  631.         {    section= -1;
  632.             current->pos= 0;
  633.             current->line= 0;
  634.         }
  635.  
  636.         /* last file processed */
  637.         if (!current) break;
  638.  
  639.         /* open file */
  640.         if (*filename)
  641.         {    if (!(fh= Open(current->name, MODE_OLDFILE)))
  642.             {    if (forward && current->prev)
  643.                 {    struct file *old= current->prev;
  644.                     free(current->name);
  645.                     free(current);
  646.                     current= old;
  647.                     section= SECT_INCLD;
  648.                     goto secterror;
  649.                 }
  650.                 PrintError_(ERR_CONTI_, GetCatalogStrQ_(MSG_NOTFOUND),
  651.                     GetCatalogStrQ_(MSG_FILE), current->name);
  652.                 goto failed;
  653.             }
  654.             Seek(fh, current->pos, OFFSET_BEGINNING);
  655.         } else
  656.         {    free(current->name);
  657.             free(current);
  658.             return fileflag= TRUE;
  659.         }
  660.  
  661.  
  662.         /* read file line by line */
  663.         forward= FALSE;
  664.         while (!forward && FGets(fh, buf, 256))
  665.         {    /* remove comments and leading spaces */
  666.             if (!(str= strchr(buf, ';'))) str= buf+strlen(buf)-1;
  667.             while (isspace(str[-1]) && (str != buf)) str--;
  668.             *str= '\0';
  669.             current->line++;
  670.             if (!*buf) continue;
  671.  
  672.             str= buf; while (isspace(*str)) str++;
  673.  
  674.             /* read command */
  675.             if (*str == '#')
  676.             {    if ((section != -1) && sectcounts[section]
  677.                     && (sectcounts[section] != count)) goto secterror;
  678.                 num= MSG_SECTION;
  679.                 section= 0;
  680.                 do str++; while (isspace(*str));
  681.                 while (s= sectnames[section])
  682.                     if (!Strnicmp(str, s, strlen(s))) break; else section++;
  683.                 if (!s) goto lineerror;
  684.                 str+= strlen(s);
  685.                 count= 0;
  686.                 if (!*str) continue;
  687.                 if (!isspace(*str)) goto lineerror;
  688.                 while (isspace(*str)) str++;
  689.             }
  690.  
  691.             switch (section)
  692.             {    case SECT_INCLD: /* include command */
  693.                     {    UBYTE quotes= 0;
  694.                         struct file *temp;
  695.  
  696.                         if (count) goto secterror;
  697.                         temp= (struct file *)MAllocQ_(sizeof(struct file));
  698.                         temp->prev= current;
  699.                         current->pos= Seek(fh, 0, OFFSET_CURRENT);
  700.                         current= temp;
  701.                         forward= TRUE;
  702.  
  703.                         s= str; if (*s == '"') quotes= 2;
  704.                         while (((!quotes && !isspace(*str))
  705.                             || (quotes && (*str == '"'))) && *str) str++;
  706.                         if (quotes) str++;
  707.                         strncpy(current->name= MAllocQ_(str-s-quotes+1), s,
  708.                             str-s-quotes);
  709.                         current->name[str-s-quotes]= '\0';
  710.                         while (isspace(*str)) str++;
  711.                     }
  712.                     break;
  713.  
  714.                 case SECT_MNAMS: /* monthnames section */
  715.                     mnflag= TRUE;
  716.                     while (*str)
  717.                     {    UBYTE quotes= 0;
  718.  
  719.                         if (count == NUMMONTHS) goto secterror;
  720.                         s= str; if (*s == '"') quotes= 2;
  721.                         while (((!quotes && !isspace(*str))
  722.                             || (quotes && (*str == '"'))) && *str) str++;
  723.                         if (quotes) str++;
  724.                         strncpy(months[count]= MAllocQ_(str-s-quotes+1), s,
  725.                             str-s-quotes);
  726.                         months[count++][str-s-quotes]= '\0';
  727.                         while (isspace(*str)) str++;
  728.                     }
  729.                     break;
  730.  
  731.                 case SECT_WDAYS: /* weekdays section */
  732.                     wdflag= TRUE;
  733.                     while (*str)
  734.                     {    UBYTE quotes= 0;
  735.  
  736.                         if (count == NUMWEEKDAYS) goto secterror;
  737.                         s= str; if (*s == '"') quotes= 2;
  738.                         while (((!quotes && !isspace(*str))
  739.                             || (quotes && (*str == '"'))) && *str) str++;
  740.                         if (quotes) str++;
  741.                         strncpy(weekdays[count]= MAllocQ_(str-s-quotes+1), s,
  742.                             str-s-quotes);
  743.                         weekdays[count++][str-s-quotes]= '\0';
  744.                         while (isspace(*str)) str++;
  745.                     }
  746.                     break;
  747.  
  748.                 case SECT_WKCNT: /* weekcount section */
  749.                     if (!Strnicmp(str, "ON", 2))
  750.                     {    counting= TRUE;
  751.                         str+= 2;
  752.                     } else if (!Strnicmp(str, "OFF", 3))
  753.                     {    counting= FALSE;
  754.                         str+= 3;
  755.                     }
  756.                     if (count++ || *str) goto secterror;
  757.                     break;
  758.  
  759.                 case SECT_FWDAY:
  760.                 case SECT_RWDAY:
  761.                     day= 0;
  762.                     while (Strnicmp(weekdays[day], str, strlen(weekdays[day])))
  763.                         if (++day == NUMWEEKDAYS) goto lineerror;
  764.                     str+= strlen(weekdays[day]);
  765.                     if (count++ || *str) goto secterror;
  766.                     if (section == SECT_FWDAY)    firstwday= day;
  767.                     else                        restwday= day;
  768.                     break;
  769.  
  770.                 case SECT_HDAYS: /* holidays section */
  771.                     newday= (struct fileday *)MAllocQ_(sizeof(struct fileday));
  772.                     newday->next= filedays;
  773.                     filedays= newday;
  774.                     newday->flags= 0;
  775.                     if (*str == '!')
  776.                     {    newday->flags= FREEDAY;
  777.                         str++;
  778.                     }
  779.                     if (*str == '%')
  780.                     {    /* Easter or Advent */
  781.                         switch (ToUpper(*++str))
  782.                         {    case 'E':
  783.                                 newday->flags|= EASTER;
  784.                                 break;
  785.                             case 'A':
  786.                                 newday->flags|= ADVENT;
  787.                                 break;
  788.                             default:
  789.                                 goto secterror;
  790.                         }
  791.                         str++;
  792.                     } else
  793.                     {    if (!isdigit(*str))
  794.                         {    /* first or last weekday */
  795.                             day= 0;
  796.                             newday->flags|=
  797.                                 (*str == '~')? LASTWDAY : FIRSTWDAY;
  798.                             if (newday->flags&LASTWDAY) str++;
  799.                             while (Strnicmp(weekdays[day], str,
  800.                                 strlen(weekdays[day])))
  801.                                 if (++day == NUMWEEKDAYS) goto secterror;
  802.                             str+= strlen(weekdays[day]);
  803.                             sscanf(str, ".%hu.%hn", &month, &end);
  804.                         } else
  805.                         {    /* normal date */
  806.                             sscanf(str, "%hu.%hu.%hn", &day, &month, &end);
  807.                         }
  808.                         str+= end;
  809.                     }
  810.  
  811.                     /* read offset */
  812.                     switch (*str)
  813.                     {    case '+':
  814.                             str++;
  815.                         case '-':
  816.                             sscanf(str, "%hd%hn", &newday->offset, &end);
  817.                             str+= end;
  818.                             break;
  819.                         default:
  820.                             newday->offset= 0;
  821.                     }
  822.  
  823.                     /* put in day, month and name */
  824.                     while (isspace(*str)) str++;
  825.                     strncpy(newday->name, str, MAXWIDTH-1);
  826.                     newday->name[MAXWIDTH-1]= '\0';
  827.                     newday->day= day;
  828.                     if (((newday->month= month-1) > NUMMONTHS-1)
  829.                         || (day > ((month == 2)? 29 : days[month-1])))
  830. secterror:            {    num= MSG_INSECTION;
  831. lineerror:                Close(fh);
  832.                         sprintf(buf, GetCatalogStrQ_(MSG_LINEERROR),
  833.                             current->line, current->name,
  834.                             GetCatalogStrQ_(num));
  835.                         PrintError_(ERR_CONTI_, buf, sectnames[section]);
  836. failed:                    /* free whole file list */
  837.                         {    struct file *old;
  838.  
  839.                             while (current)
  840.                             {    old= current->prev;
  841.                                 free(current->name);
  842.                                 free(current);
  843.                                 current= old;
  844.                             }
  845.                         }
  846.                         return fileflag= FALSE;
  847.                     }
  848.                     break;
  849.  
  850.                 case -1: /* no section */
  851.                     num= MSG_NOSECTION;
  852.                     goto lineerror;
  853.             }
  854.         }
  855.  
  856.         /* close file, abort if error occured */
  857.         {    LONG error;
  858.  
  859.             error= IoErr();
  860.             Close(fh);
  861.             if (error)
  862.             {    PrintError_(ERR_CONTI_, GetCatalogStrQ_(MSG_FILEERROR),
  863.                     current->name);
  864.                 goto failed;
  865.             }
  866.         }
  867.     }
  868.  
  869.     return fileflag= TRUE;
  870. }
  871. #undef SECT_INCLD
  872. #undef SECT_MNAMS
  873. #undef SECT_WDAYS
  874. #undef SECT_WKCNT
  875. #undef SECT_FWDAY
  876. #undef SECT_RWDAY
  877. #undef SECT_HDAYS
  878.  
  879. /*==== open printer ====*/
  880. BOOL OpenPrinter_(void)
  881. {    prtport= CreateMsgPort();
  882.     prtreq= (struct IOStdReq *)CreateIORequest(prtport,
  883.         sizeof(struct IOStdReq));
  884.  
  885.     if (OpenDevice("printer.device", 0, (struct IORequest *)prtreq, 0))
  886.     {    PrintError_(ERR_ABORT_, GetCatalogStrQ_(MSG_PRINTERUSED));
  887.         return FALSE;
  888.     } else
  889.         return TRUE;
  890. }
  891.  
  892. /*==== close printer ====*/
  893. void ClosePrinter_(void)
  894. {    if (prtport)
  895.     {    struct Message *msg;
  896.  
  897.         while (msg= GetMsg(prtport)) ReplyMsg(msg);
  898.         DeleteMsgPort(prtport);
  899.         prtport= NULL;
  900.     }
  901.     if (prtreq)
  902.     {    CloseDevice((struct IORequest *)prtreq);
  903.         DeleteIORequest(prtreq);
  904.         prtreq= NULL;
  905.     }
  906. }
  907.  
  908. /*==== do printer.device write command ====*/
  909. BOOL ExecPrtIO_(const TEXT *data)
  910. {    prtreq->io_Data= (APTR)data;
  911.     prtreq->io_Length= -1;
  912.     if (DoIO((struct IORequest *)prtreq))
  913.     {    PrintError_(ERR_ABORT_, GetCatalogStrQ_(MSG_PRINTPROBL));
  914.         return FALSE;
  915.     }
  916.     return TRUE;
  917. }
  918.  
  919. BOOL ExecChrIO_(const TEXT cdata)
  920. {    static TEXT s[2];
  921.  
  922.     s[0]= cdata;
  923.     return ExecPrtIO_(s);
  924. }
  925.  
  926. /*==== main printing program ====*/
  927. #define DoPrtIO_(x) { if (!ExecPrtIO_(x)) goto prtfailed; }
  928. #define DoChrIO_(x) { if (!ExecChrIO_(x)) goto prtfailed; }
  929. #define SetPrtIO_(cmd)    prtreq->io_Command= cmd
  930. #define ESC "\x1b"
  931. #define CSI    "\x9b"
  932. UBYTE PrintCalendar_(UBYTE quart, UBYTE pitch, UBYTE ibmpc)
  933. {    /*- miscellaneous variables -*/
  934.     TEXT buf[256];                /* buffer for sprintf() */
  935.     struct yearday *point[3];    /* pointer to holiday entries of each month */
  936.     UBYTE week[3];                /* current week number of each month */
  937.     UBYTE day, month;            /* loop variables */
  938.     UBYTE colwidth;                /* width of one column according to pitch */
  939.     BOOL allquarts;                /* TRUE if whole year is requested */
  940.  
  941.     /*- graphical characters [0]= IBMPC, [1]= ASCII -*/
  942.     static TEXT ul[]= "+\xd2", ulm[]= "+\xc2", um[]= "+\xd6", ur[]= "+\xb7",
  943.                 ml[]= "+\xc7", mm[]= "+\xd7", mr[]= "+\xb6",
  944.                 m1lm[]= "+\xc5", m2lm[]= "+\xd8",
  945.                 d1lm[]= "+\xc1", d2lm[]= "+\xcf",
  946.                 s1l[]= ":\xb3", s2l[]= "|\xba", h1l[]= "-\xc4", h2l[]= "=\xcd";
  947.  
  948.     /*- separator lines -*/
  949.     static TEXT t1l[6], t1[MAXWIDTH], t2l[6], t2[MAXWIDTH];
  950.  
  951.     /*- format strings -*/
  952.     TEXT *form1, *form2, *form3;
  953.  
  954.     /*- re-initialize parameters -*/
  955.     if (allquarts= quart > 3)    quart= 0; else quart*= 3;
  956.     if (pitch > 3)                pitch= DEFPITCH;
  957.  
  958.     /*- initialize printer -*/
  959.     if (!OpenPrinter_()) goto prtfailed;
  960.     SetPrtIO_(CMD_WRITE);
  961.     DoPrtIO_(ESC "#1" CSI "0z");
  962.  
  963.     /*- set formats according to pitch -*/
  964.     switch (pitch)
  965.     {    case 0: /* PICA 10cpi= 58 chars/line= 19 chars/col */
  966.             colwidth= 19;
  967.             DoPrtIO_(CSI "0w");
  968.             form1= "%18s";
  969.             form2= "%-12.12s";
  970.             form3= "%-7.7s " CSI "3m-%2.2ld-" CSI "23m";
  971.             break;
  972.         case 1: /* ELITE 12cpi= 69 chars/line= 22 chars/col */
  973.             colwidth= 22;
  974.             DoPrtIO_(CSI "0w" CSI "2w");
  975.             form1= "%21s";
  976.             form2= "%-15.15s";
  977.             form3= "%-10.10s " CSI "3m-%2.2ld-" CSI "23m";
  978.             break;
  979.         case 2: /* SEMI 15cpi= 87 chars/line= 28 chars/col */
  980.             colwidth= 28;
  981.             DoPrtIO_(CSI "0w");
  982.             form1= "%27s";
  983.             form2= "%-21.21s";
  984.             form3= "%-16.16s " CSI "3m%-2.2ld-" CSI "23m";
  985.             break;
  986.         default: /* FINE 17cpi= 98 chars/line= 32 chars/col */
  987.             colwidth= 32;
  988.             DoPrtIO_(CSI "0w" CSI "4w");
  989.             form1= "%31s";
  990.             form2= "%-25.25s";
  991.             form3= "%-20.20s " CSI "3m-%2.2ld-" CSI "23m";
  992.     }
  993.  
  994.     /*- set line separators according to ibmpc graphics flag -*/
  995.     {    UBYTE c1= h1l[ibmpc], c2= h2l[ibmpc], i;
  996.  
  997.         for (i= 0; i < 5; i++)    {    t1l[i]= c1; t2l[i]= c2;    }
  998.         for (i= 0; i < 25; i++)    {    t1[i]= c1; t2[i]= c2;    }
  999.         t1[colwidth-7]= t2[colwidth-7]= '\0';
  1000.     }
  1001.  
  1002.     /*- print loop for one sheet -*/
  1003.     do
  1004.     {    /* print number of year */
  1005.         sprintf(buf, CSI "1m" CSI "4m" CSI "6w%ld" CSI "5w" CSI "0m\n\n",
  1006.             year);
  1007.         DoPrtIO_(buf);
  1008.  
  1009.         /* print month names */
  1010.         {    UBYTE slen, left, i;
  1011.  
  1012.             for (month= 0; month < 3; month++)
  1013.             {    point[month]= yeardays[quart+month];
  1014.                 week[month]= firstweek[quart+month];
  1015.  
  1016.                 slen= strlen(GetLocaleStrQ_(MON_1+quart+month));
  1017.                 left= (colwidth-slen)/2+((colwidth-slen)&1);
  1018.                 for (i= 0; i < left; i++) buf[i]= ' ';
  1019.                 strcpy(&buf[left], GetLocaleStrQ_(MON_1+quart+month));
  1020.                 DoPrtIO_(buf);
  1021.                 buf[left-((colwidth-slen)&1)]= '\0';
  1022.                 DoPrtIO_(buf);
  1023.             }
  1024.             DoChrIO_('\n');
  1025.         }
  1026.  
  1027.         /* print first separator line */
  1028.         if (ibmpc) SetPrtIO_(PRD_RAWWRITE);
  1029.         for (month= 0; month < 3; month++)
  1030.         {    DoChrIO_((month? ul : um)[ibmpc]);
  1031.             DoPrtIO_(t1l);
  1032.             DoChrIO_(ulm[ibmpc]);
  1033.             DoPrtIO_(t1);
  1034.         }
  1035.         DoChrIO_(ur[ibmpc]);
  1036.         SetPrtIO_(CMD_WRITE);
  1037.         DoChrIO_('\n');
  1038.  
  1039.         /* print all days line by line */
  1040.         for (day= 1; day <= NUMDAYS; day++)
  1041.         {    /* print days of a line */
  1042.             if (ibmpc) SetPrtIO_(PRD_RAWWRITE);
  1043.             for (month= 0; month < 3; month++)
  1044.             {    DoChrIO_(s2l[ibmpc]);
  1045.                 if (day > days[quart+month]) /* empty line */
  1046.                 {    sprintf(buf, form1, "");
  1047.                     DoPrtIO_(buf);
  1048.                 } else
  1049.                 {    /* day with weekday, date number, holiday text */
  1050.                     TEXT *str= "";
  1051.                     BOOL bold;
  1052.  
  1053.                     bold= FALSE;
  1054.                     if ((firstday[quart+month]+day)%NUMWEEKDAYS == restwday)
  1055.                         bold= TRUE;
  1056.                     if (point[month] && (point[month]->day == day))
  1057.                     {    str= point[month]->name;
  1058.                         if (point[month]->flags&FREEDAY) bold= TRUE;
  1059.                         point[month]= point[month]->next;
  1060.                     }
  1061.                     SetPrtIO_(CMD_WRITE);
  1062.                     sprintf(buf, "%s%2.2s %2ld%s",
  1063.                         bold? CSI "1m" : "",
  1064.                         GetLocaleStrQ_(ABDAY_1+(firstday[quart+month]+day)
  1065.                             %NUMWEEKDAYS),
  1066.                         day,
  1067.                         bold? CSI "0m" : "");
  1068.                     DoPrtIO_(buf);
  1069.                     if (ibmpc) SetPrtIO_(PRD_RAWWRITE);
  1070.                     DoChrIO_(s1l[ibmpc]);
  1071.                     SetPrtIO_(CMD_WRITE);
  1072.                     if (!counting || ((firstday[quart+month]+day)
  1073.                         %NUMWEEKDAYS != firstwday))
  1074.                         sprintf(buf, form2, str);
  1075.                     else
  1076.                     {    if ((quart+month == NUMMONTHS-1) && (day >= 29))
  1077.                             week[month]= 1;
  1078.                         else if (day != 1) week[month]++;
  1079.                         sprintf(buf, form3, str, week[month]);
  1080.                     }
  1081.                     DoPrtIO_(buf);
  1082.                     if (ibmpc) SetPrtIO_(PRD_RAWWRITE);
  1083.                 }
  1084.             }
  1085.             DoChrIO_(s2l[ibmpc]);
  1086.             SetPrtIO_(CMD_WRITE);
  1087.             DoChrIO_('\n');
  1088.  
  1089.             /* print separator line */
  1090.             for (month= 0; month < 3; month++)
  1091.             {    if (ibmpc) SetPrtIO_(PRD_RAWWRITE);
  1092.                 if (day > days[quart+month])
  1093.                 {    DoChrIO_((((month < 3) && (day > days[quart+month+1]))?
  1094.                         mr : s2l)[ibmpc]);
  1095.                     sprintf(buf, form1, ""); /* expand */
  1096.                     DoPrtIO_(buf);
  1097.                 } else
  1098.                 {    DoChrIO_(((month && (day <= days[quart+month-1]))? mm : ml)
  1099.                         [ibmpc]);
  1100.                     if ((firstday[quart+month]+day+1)%NUMWEEKDAYS != firstwday)
  1101.                     {    DoPrtIO_(t1l);
  1102.                         DoChrIO_(((day == days[quart+month])? d1lm : m1lm)
  1103.                             [ibmpc]);
  1104.                         DoPrtIO_(t1);
  1105.                     } else
  1106.                     {    DoPrtIO_(t2l);
  1107.                         DoChrIO_(((day == days[quart+month])? d2lm : m2lm)
  1108.                             [ibmpc]);
  1109.                         DoPrtIO_(t2);
  1110.                     }
  1111.                 }
  1112.             }
  1113.             DoChrIO_(mr[ibmpc]);
  1114.             SetPrtIO_(CMD_WRITE);
  1115.             DoChrIO_('\n');
  1116.  
  1117.             /* interrupt printing if user presses CTRL-C */
  1118.             {    struct IntuiMessage *imsg= NULL;
  1119.                 BOOL brk;
  1120.  
  1121.                 brk= ((SetSignal(0, 0)&SIGBREAKF_CTRL_C)
  1122.                     || (win && (imsg= GT_GetIMsg(win->UserPort))
  1123.                     && ((imsg->Class == IDCMP_CLOSEWINDOW)
  1124.                     || (imsg->Class == IDCMP_GADGETUP))));
  1125.                 if (imsg) GT_ReplyIMsg(imsg);
  1126.                 if (brk)
  1127.                     if(!PrintError_(ERR_CONTI_|ERR_ABORT_, 
  1128.                         GetCatalogStrQ_(MSG_USERBREAK)))
  1129.                         goto prtfailed;
  1130.             }
  1131.         }
  1132.  
  1133.         /* print form feed */
  1134.         DoChrIO_('\f');
  1135.     } while (allquarts && ((quart+= 3) < 12));
  1136.  
  1137.     /*- reset and close printer -*/
  1138.     DoPrtIO_(ESC "#1");
  1139.     ClosePrinter_();
  1140.     return RETURN_OK;
  1141.  
  1142. prtfailed:
  1143.     /*- close printer -*/
  1144.     ClosePrinter_();
  1145.     return RETURN_ERROR;
  1146. }
  1147. #undef DoPrtIO_
  1148. #undef DoChrIO_
  1149. #undef SetPrtIO_
  1150. #undef ESC
  1151. #undef CSI
  1152.  
  1153. /*=== open window with all gadgets ====*/
  1154. void OpenWinAndGadgets_(void)
  1155. {    struct RastPort *rp;    /* pointer to public screen's rastport */
  1156.     UWORD xsize;            /* font's width */
  1157.     UWORD winwidth;            /* window width */
  1158.     UWORD textwidth= 0;        /* maximum width of gadgets' text */
  1159.     UWORD fieldwidth= 0;    /* maximum width of gagdets */
  1160.     UWORD u;                /* width of underscore character */
  1161.     UWORD n;                /* temporary width variable */
  1162.     TEXT *str;                /* temporary string variable */
  1163.     BYTE i;                    /* loop variable */
  1164.     static struct NewGadget newgad; /* used with CreateGadget() */
  1165.  
  1166.     /*- my newwindow structure -*/
  1167.     static struct NewWindow newwin=
  1168.     {    0, 0, 0, 0, 0, 1,
  1169.         CYCLEIDCMP|NUMBERIDCMP|STRINGIDCMP|BUTTONIDCMP|IDCMP_GADGETUP|
  1170.             IDCMP_GADGETDOWN|IDCMP_CLOSEWINDOW|IDCMP_RAWKEY|IDCMP_VANILLAKEY,
  1171.         WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_ACTIVATE|
  1172.             WFLG_SMART_REFRESH|WFLG_GIMMEZEROZERO,
  1173.         NULL, NULL, PRGNAME, NULL, NULL, 0, 0, 0, 0, PUBLICSCREEN
  1174.     };
  1175.  
  1176.     /*- get width of system font -*/
  1177.     rp= &pubscr->RastPort;
  1178.     if (rp->Font->tf_Flags&FPF_PROPORTIONAL)
  1179.     {    i= max(rp->Font->tf_LoChar, ' ');
  1180.  
  1181.         xsize= 0;
  1182.         do
  1183.         {    if ((n= TextLength(rp, &i, 1)) > xsize) xsize= n;
  1184.         } while ((i != (BYTE)rp->Font->tf_HiChar) && (i++ != (BYTE)'~'));
  1185.     } else
  1186.         xsize= rp->Font->tf_XSize;
  1187.  
  1188.     /*- resize file requester gadget image -*/
  1189.     if (!ResizeImage_(&frimage, 2*xsize+2, 2+rp->Font->tf_YSize))
  1190.         goto failed;
  1191.  
  1192.     /*- calculate all gadgets' widths -*/
  1193.     u= TextLength(rp, "_", 1);
  1194.     i= -1; while (gads[++i].line != -1)
  1195.     {    switch (gads[i].kind)
  1196.         {    case CYCLE_KIND:
  1197.                 {    BYTE j= -1;
  1198.  
  1199.                     TEXT **s= (TEXT **)gads[i].misc;
  1200.                     gads[i].width= 0;
  1201.                     while (s[++j])
  1202.                     {    n= TextLength(rp, s[j], strlen(s[j]));
  1203.                         if (n > gads[i].width) gads[i].width= n;
  1204.                     }
  1205.                 }
  1206.                 gads[i].width+= 4*INTERWIDTH;
  1207.                 if (gads[i].width > fieldwidth) fieldwidth= gads[i].width;
  1208. calctext:        str= GetCatalogStrQ_(gads[i].textnum);
  1209.                 n= TextLength(rp, str, strlen(str));
  1210.                 if (strchr(str, '_')) n-= u;
  1211.                 if (n > textwidth) textwidth= n;
  1212.                 break;
  1213.             case BUTTON_KIND:
  1214.                 str= GetCatalogStrQ_(gads[i].textnum);
  1215.                 gads[i].width=
  1216.                     2*INTERWIDTH+TextLength(rp, str, strlen(str));
  1217.                 if (strchr(str, '_')) gads[i].width-= u;
  1218.                 break;
  1219.             default: /* STRING_KIND, INTEGER_KIND or GENERIC_KIND */
  1220.                 n= xsize*(gads[i].width+1)+INTERWIDTH;
  1221.                 gads[i].width= n;
  1222.                 if ((gads[i].left != RIGHT_) && (gads[i].left > LEFT_))
  1223.                     n+= xsize*gads[i].left+INTERWIDTH+2;
  1224.                 if (n > fieldwidth) fieldwidth= n;
  1225.                 goto calctext;
  1226.         }
  1227.     }
  1228.  
  1229.     /*- set window width correctly -*/
  1230.     winwidth= textwidth+fieldwidth+INTERWIDTH;
  1231.     i= -1; while (gads[++i].line != -1)
  1232.     {    if ((gads[i].left == LEFT_) && (gads[i+1].left == RIGHT_)
  1233.             && (gads[i].line == gads[i+1].line)
  1234.             && (gads[i].kind == BUTTON_KIND)
  1235.             && (gads[i+1].kind == BUTTON_KIND))
  1236.         {    n= gads[i].width+gads[i+1].width;
  1237.             if (n > winwidth) winwidth= n;
  1238.         }
  1239.     }
  1240.     winwidth+= 3*INTERWIDTH;
  1241.  
  1242.     /*- bring gadgets to screen -*/
  1243.     do
  1244.     {    CreateContext(&congad);
  1245.         newgad.ng_VisualInfo= vi;
  1246.         newgad.ng_TextAttr= pubscr->Font;
  1247.         newgad.ng_Height= 6+rp->Font->tf_YSize;
  1248.         newgad.ng_TopEdge= INTERHEIGHT;
  1249.         newgad.ng_GadgetID= 0;
  1250.         i= -1; while (gads[++i].line != -1)
  1251.         {    if (gads[i].kind == BUTTON_KIND)
  1252.             {    newgad.ng_LeftEdge= (gads[i].left == RIGHT_)?
  1253.                     winwidth-INTERWIDTH-gads[i].width : INTERWIDTH;
  1254.                 newgad.ng_Flags= PLACETEXT_IN;
  1255.             } else
  1256.             {    newgad.ng_LeftEdge= 2*INTERWIDTH+textwidth;
  1257.                 newgad.ng_Flags= PLACETEXT_LEFT;                
  1258.             }
  1259.             newgad.ng_Width= gads[i].width;
  1260.             newgad.ng_GadgetText= GetCatalogStrQ_(gads[i].textnum);
  1261.             gads[i].gad= CreateGadget(gads[i].kind,
  1262.                 i? gads[i-1].gad : congad, &newgad,
  1263.                 GT_Underscore, (ULONG)'_',
  1264.                 STRINGA_ExitHelp, TRUE,
  1265.                 GTST_MaxChars, 256,
  1266.                 GTCY_Active, gads[i].contents,
  1267.                 (gads[i].kind == STRING_KIND)? GTST_String
  1268.                 : (gads[i].kind == NUMBER_KIND)? GTIN_Number
  1269.                 : GTCY_Labels, gads[i].misc,
  1270.                 GA_Disabled, i == GID_STOP,
  1271.                 TAG_DONE);
  1272.             if ((gads[i].left != RIGHT_) && (gads[i].left > LEFT_))
  1273.             {    struct IntuiText *it= gads[i].gad->GadgetText;
  1274.  
  1275.                 n= xsize*(gads[i].left+1)+INTERWIDTH+2;
  1276.                 gads[i].gad->LeftEdge+= n;
  1277.                 while (it)
  1278.                 {    it->LeftEdge-= n;
  1279.                     it= it->NextText;
  1280.                 }
  1281.             }
  1282.             if (gads[i+1].line != -1)
  1283.             {    n= gads[i+1].line-gads[i].line;
  1284.                 while (n-- > 0)
  1285.                     newgad.ng_TopEdge+= newgad.ng_Height+INTERHEIGHT;
  1286.             }                
  1287.             newgad.ng_GadgetID++;
  1288.         }
  1289.  
  1290.         if (!gads[i-1].gad)
  1291.         {    if (!PrintError_(ERR_RETRY_|ERR_QUIT_,
  1292.                 GetCatalogStrQ_(MSG_NOMEMORY)))
  1293.                 goto failed;
  1294.             FreeGadgets(congad);
  1295.             congad= NULL;
  1296.         } else
  1297.             break;
  1298.     } while (TRUE);
  1299.  
  1300.     /*- open window -*/
  1301.     while (!(win= OpenWindowTags(&newwin,
  1302.         WA_ScreenTitle, (ULONG)PRGNAME " - (c)1991 by Dieter Temme",
  1303.         WA_InnerWidth, winwidth,
  1304.         WA_InnerHeight, newgad.ng_TopEdge+newgad.ng_Height+INTERHEIGHT,
  1305.         TAG_DONE)))
  1306.         if (!PrintError_(ERR_RETRY_|ERR_QUIT_,
  1307.             GetCatalogStrQ_(MSG_NOWINDOW)))
  1308. failed:        exit(RETURN_FAIL);
  1309.  
  1310.     /*- unlock public default screen and set signals variable -*/
  1311.     UnlockPubScreen(NULL, pubscr); pubscr= NULL;
  1312.     signals= 1<<win->UserPort->mp_SigBit;
  1313.  
  1314.     /*- define file requester gadget -*/
  1315.     gads[GID_FREQ].gad->Flags= GFLG_GADGIMAGE;
  1316.     gads[GID_FREQ].gad->Activation= GACT_RELVERIFY;
  1317.     gads[GID_FREQ].gad->GadgetType|= GTYP_BOOLGADGET;
  1318.     gads[GID_FREQ].gad->GadgetRender= (APTR)&frimage;
  1319.     DrawBevelBox(win->RPort, gads[GID_FREQ].gad->LeftEdge,
  1320.         gads[GID_FREQ].gad->TopEdge,
  1321.         gads[GID_FREQ].gad->Width, gads[GID_FREQ].gad->Height,
  1322.         GT_VisualInfo, (ULONG)vi,
  1323.         TAG_DONE);
  1324.  
  1325.     /*- add gadgets to window -*/
  1326.     AddGList(win, congad, ~0, -1, NULL);
  1327.     RefreshGList(congad, win, NULL, -1);
  1328.     GT_RefreshWindow(win, NULL);
  1329. }
  1330.  
  1331. /*==== process filename ====*/
  1332. #define NOREAD    0
  1333. #define READ    1
  1334. #define FORCED    2
  1335. void ProcessFilename_(UBYTE readflag, TEXT *newname)
  1336. {    if ((readflag == FORCED) || Stricmp(newname, name))
  1337.     {    if (name) free(name);
  1338.         name= strcpy((TEXT *)MAllocQ_(strlen(newname)+1), newname);
  1339.         fileflag= FALSE;
  1340.     }
  1341.  
  1342.     if (readflag && !fileflag)
  1343.     {    ReadFile_(name);
  1344.         CalcYear_(FALSE, year);
  1345.     }
  1346.  
  1347.     GT_SetGadgetAttrs(gads[GID_PRINT].gad, win, NULL,
  1348.         GA_Disabled, TRUE-fileflag,
  1349.         TAG_DONE);
  1350. }
  1351.  
  1352. /*==== read icon's tool types or bundled file ====*/
  1353. void ReadToolTypes_(struct WBStartup *wbarg)
  1354. {    struct DiskObject *obj;
  1355.     TEXT *s, **tt;
  1356.     ULONG i;
  1357.  
  1358.     if (IconBase= OpenLibrary("icon.library", 0))
  1359.     {    if (obj= GetDiskObject(wbarg->sm_ArgList->wa_Name))
  1360.         {    /* scan tool types */
  1361.             if ((s= FindToolType(tt, "YEAR")))
  1362.                 CalcYear_(FALSE, atol(s));
  1363.             if (s= FindToolType(tt, "QUARTER"))
  1364.             {    if (!Stricmp(s, "ALL"))
  1365.                     gads[GID_QUART].contents= 4;
  1366.                 else if ((i= (ULONG)atol(s)) <= 3)
  1367.                     gads[GID_QUART].contents= (UBYTE)i;
  1368.             }
  1369.             if ((s= FindToolType(tt= obj->do_ToolTypes, "FILE")) && *s)
  1370.                 ProcessFilename_(READ, s);
  1371.             if (s= FindToolType(tt, "PITCH"))
  1372.             {    if (!Stricmp(s, "PICA")) gads[GID_PITCH].contents= 0;
  1373.                 else if (!Stricmp(s, "ELITE")) gads[GID_PITCH].contents= 1;
  1374.                 else if (!Stricmp(s, "SEMI")) gads[GID_PITCH].contents= 2;
  1375.                 else if (!Stricmp(s, "FINE")) gads[GID_PITCH].contents= 3;
  1376.             }
  1377.             if (s= FindToolType(tt, "GRAPHICS"))
  1378.                 if (!Stricmp(s, "ASCII")) gads[GID_GRAPH].contents= FALSE;
  1379.                 else if (!Stricmp(s, "IBMPC")) gads[GID_GRAPH].contents= TRUE;
  1380.                 FreeDiskObject(obj);
  1381.  
  1382.             /* get bundled defaults file icon */
  1383.             if (wbarg->sm_NumArgs > 1)
  1384.             {    struct WBArg *argptr= &wbarg->sm_ArgList[1];
  1385.                 ULONG x, y;
  1386.                 TEXT *str;
  1387.                 BPTR lock;
  1388.  
  1389.                 y= strlen(argptr->wa_Name)+2;
  1390.                 CurrentDir(lock= CurrentDir((BPTR)NULL));
  1391.                 if (SameLock(lock, argptr->wa_Lock) == LOCK_SAME)
  1392.                     str= strcpy((TEXT *)MAllocQ_(y), argptr->wa_Name);
  1393.                 else
  1394.                 {    x= 256;
  1395.                     do
  1396.                     {    if (str) free(str);
  1397.                         str= MAllocQ_(x+y);
  1398.                     } while (!NameFromLock(argptr->wa_Lock, str, x));
  1399.                     AddPart(str, argptr->wa_Name, x+y);
  1400.                 }
  1401.                 ProcessFilename_(READ, str);
  1402.             }
  1403.         }
  1404.         CloseLibrary(IconBase);
  1405.     }
  1406. }
  1407.  
  1408. /*==== process application window messages ====*/
  1409. void ProcessAppMessages_(void)
  1410. {    struct AppMessage *amsg;
  1411.     struct WBArg *argptr;
  1412.     ULONG x, y;
  1413.     TEXT *str;
  1414.     BPTR lock;
  1415.  
  1416.     while (amsg= (struct AppMessage *)GetMsg(appport))
  1417.     {    str= NULL;
  1418.         argptr= &amsg->am_ArgList[amsg->am_NumArgs-1];
  1419.         y= strlen(argptr->wa_Name)+2;
  1420.         CurrentDir(lock= CurrentDir((BPTR)NULL));
  1421.         if (SameLock(lock, argptr->wa_Lock) == LOCK_SAME)
  1422.             str= strcpy((TEXT *)MAllocQ_(y), argptr->wa_Name);
  1423.         else
  1424.         {    x= 256;
  1425.             do
  1426.             {    if (str) free(str);
  1427.                 str= MAllocQ_(x+y);
  1428.             } while (!NameFromLock(argptr->wa_Lock, str, x));
  1429.             AddPart(str, argptr->wa_Name, x+y);
  1430.         }
  1431.         ProcessFilename_(READ, str);
  1432.  
  1433.         ReplyMsg((struct Message *)amsg);
  1434.     }
  1435. }
  1436.  
  1437. /*==== process window messages ====*/
  1438. #define STRINGINFO(gid) ((struct StringInfo *)gads[gid].gad->SpecialInfo)
  1439. #define REQPRINT    1
  1440. #define REQEXIT        2
  1441. UBYTE ProcessWindowMessages_(void)
  1442. {    struct IntuiMessage *imsg;        /* pointer to window message */
  1443.     TEXT c;                            /* character of VANILLAKEY message */
  1444.     TEXT fname[31];                    /* filename without path */
  1445.     UBYTE rc= 0;                    /* return code */
  1446.  
  1447.     while (!rc && (imsg= GT_GetIMsg(win->UserPort)))
  1448.     {    switch (imsg->Class)
  1449.         {    case IDCMP_GADGETUP:
  1450.                 switch (c= ((struct Gadget *)imsg->IAddress)->GadgetID)
  1451.                 {    case GID_YEAR:
  1452.                         CalcYear_(FALSE, STRINGINFO(GID_YEAR)->LongInt);
  1453.                         break;
  1454.  
  1455.                     case GID_FILE:
  1456.                         if (imsg->Code == 0x5f) goto outhelp;
  1457.                         ProcessFilename_(FORCED, STRINGINFO(GID_FILE)->Buffer);
  1458.                         break;
  1459.  
  1460.                     case GID_FREQ:
  1461.                     {    ULONG idcmpflags;
  1462.  
  1463.                         ProcessFilename_(NOREAD, STRINGINFO(GID_FILE)->Buffer);
  1464.                         strncpy(fname, FilePart(name), 30);
  1465.                         fname[30]= '\0';
  1466.                         *PathPart(name)= '\0';
  1467.                         if (pimage)
  1468.                         {    idcmpflags= win->IDCMPFlags;
  1469.                             ModifyIDCMP(win, IDCMP_MENUPICK);
  1470.                             SetPointer(win, pimage, 16, 16, -6, 0);
  1471.                         }
  1472.                         if (AslRequestTags((APTR)freq,
  1473.                             ASLFR_InitialDrawer, (ULONG)name,
  1474.                             ASLFR_InitialFile, (ULONG)fname,
  1475.                             TAG_DONE))
  1476.                         {    UWORD i;
  1477.                             TEXT *tmpstr;
  1478.  
  1479.                             tmpstr= strcpy(MAllocQ_(i= strlen(freq->fr_Drawer)
  1480.                                 +strlen(freq->fr_File)+3), freq->fr_Drawer);
  1481.                             AddPart(tmpstr, freq->fr_File, i);
  1482.                             ProcessFilename_(FORCED, tmpstr);
  1483.                         }
  1484.                         if (pimage)
  1485.                         {    ClearPointer(win);
  1486.                             ModifyIDCMP(win, idcmpflags);
  1487.                         }
  1488.                         break;
  1489.                     }
  1490.  
  1491.                     case GID_PRINT:
  1492. print:                    ProcessFilename_(READ, STRINGINFO(GID_FILE)->Buffer);
  1493.                         rc= REQPRINT;
  1494.                         break;
  1495.  
  1496.                     default:
  1497.                         gads[c].contents= (UBYTE)imsg->Code;
  1498.                 }
  1499.                 break;
  1500.             case IDCMP_VANILLAKEY:
  1501.                 c= (TEXT)ToUpper(imsg->Code);
  1502.                 if (c == GetGadgetChar_(MSG_YEAR_GADTXT))
  1503.                     ActivateGadget(gads[GID_YEAR].gad, win, NULL);
  1504.                 else if (c == GetGadgetChar_(MSG_FILE_GADTXT))
  1505.                     ActivateGadget(gads[GID_FILE].gad, win, NULL);
  1506.                 else if (c == GetGadgetChar_(MSG_QUART_GADTXT))
  1507.                 {    gads[GID_QUART].contents=
  1508.                         (gads[GID_QUART].contents+1)%5;
  1509.                     c= GID_QUART;
  1510.                     goto setattr;
  1511.                 } else if (c == GetGadgetChar_(MSG_PITCH_GADTXT))
  1512.                 {    gads[GID_PITCH].contents=
  1513.                         (gads[GID_PITCH].contents+1)&3;
  1514.                     c= GID_PITCH;
  1515.                     goto setattr;
  1516.                 } else if (c == GetGadgetChar_(MSG_GRAPH_GADTXT))
  1517.                 {    gads[GID_GRAPH].contents^= TRUE;
  1518.                     c= GID_GRAPH;
  1519. setattr:            GT_SetGadgetAttrs(gads[c].gad, win, NULL,
  1520.                         GTCY_Active, gads[c].contents,
  1521.                         TAG_DONE);
  1522.                 } else if (c == GetGadgetChar_(MSG_PRINT_GAD))
  1523.                         goto print;
  1524.                 else if (c == '\x1b')
  1525.                         goto quit;
  1526.                 break;
  1527.             case IDCMP_RAWKEY:
  1528.                 if (imsg->Code == 0x5f)
  1529. outhelp:            PrintError_(ERR_CONTI_, "*** " PRGNAME VERSION " ***"
  1530.                         " - (c)1991 by Dieter Temme\n\n%s",
  1531.                         GetCatalogStrQ_(MSG_HELP));
  1532.                 break;
  1533.             case IDCMP_CLOSEWINDOW:
  1534. quit:            rc= REQEXIT;
  1535.         }
  1536.         GT_ReplyIMsg(imsg);
  1537.     }
  1538.     return rc;
  1539. }
  1540. #undef STRINGINFO
  1541.  
  1542. /*==== main program (Workbench) ====*/
  1543. int guimain(struct WBStartup *wbarg)
  1544. {    /*- miscellaneous variables -*/
  1545.     TEXT *name= NULL;        /* pointer to filename including path */
  1546.     struct RastPort *rp;    /* pointer to public screen's rastport */
  1547.     UWORD xsize;            /* font's width */
  1548.     UBYTE flag;                /* contains flags REQPRINT and REQEXIT */
  1549.  
  1550.     /*- cycle gadget lists -*/
  1551.     static TEXT *quartlist[]= /* is localized, see below */
  1552.     {    "a      ", "b      ", "c      ", "d      ", NULL, NULL
  1553.     };
  1554.     static TEXT *pitchlist[5]; /* is localized, see below */
  1555.     static TEXT *graphlist[]=
  1556.     {    "+-=:|", "IBM PC", NULL
  1557.     };
  1558.  
  1559.     /*- copy busy mouse pointer image into ChipMem -*/
  1560.     while (!(pimage= AllocMem(sizeof(mouseimage), MEMF_CHIP)))
  1561.         if (!PrintError_(ERR_RETRY_|ERR_QUIT_, GetCatalogStrQ_(MSG_NOMEMORY)))
  1562.             return RETURN_FAIL;
  1563.     CopyMem(mouseimage, pimage, sizeof(mouseimage));
  1564.  
  1565.     /*- open additional libraries -*/
  1566.     AslBase= OpenLibraryQ_("asl.library");
  1567.     GadToolsBase= OpenLibraryQ_("gadtools.library");
  1568.     GfxBase= OpenLibraryQ_("graphics.library");
  1569.     WorkbenchBase= OpenLibraryQ_("workbench.library");
  1570.  
  1571.     /*- set current directory to program's directory -*/
  1572.     lock= CurrentDir(wbarg->sm_ArgList->wa_Lock);
  1573.  
  1574.     /*- fill in gads[].misc and cycle gadget lists -*/
  1575.     gads[GID_QUART].misc= (ULONG)quartlist;
  1576.     gads[GID_PITCH].misc= (ULONG)pitchlist;
  1577.     gads[GID_GRAPH].misc= (ULONG)graphlist;
  1578.     {    UBYTE i;
  1579.  
  1580.         for (i= 0; i <= 3; i++)
  1581.         {    pitchlist[i]= GetCatalogStrQ_(MSG_PICA_GAD+i);
  1582.             sprintf(quartlist[i], "%3.3s-%3.3s",
  1583.                 GetLocaleStrQ_(ABMON_1+3*i), GetLocaleStrQ_(ABMON_3+3*i));
  1584.         }
  1585.     }
  1586.     quartlist[4]= GetCatalogStrQ_(MSG_ALL_GAD);
  1587.     pitchlist[4]= NULL;
  1588.  
  1589.     /*- lock default public screen, get visual information -*/
  1590.     pubscr= LockPubScreen(NULL);
  1591.     if (!(vi= GetVisualInfo(pubscr, TAG_DONE)))
  1592.         return RETURN_FAIL;
  1593.  
  1594.     /*- open window with gadgets -*/
  1595.     OpenWinAndGadgets_();
  1596.  
  1597.     /*- add window to application window list -*/
  1598.     if (appport= CreateMsgPort())
  1599.     {    appwin= AddAppWindowA(1, 0, win, appport, NULL);
  1600.         signals|= 1<<appport->mp_SigBit;
  1601.     }
  1602.  
  1603.     /*- initialize a file requester structure -*/
  1604.     freq= (struct FileRequest *)AllocAslRequestTags(ASL_FileRequest,
  1605.         ASLFR_Window, (ULONG)win,
  1606.         ASLFR_TitleText, (ULONG)GetCatalogStrQ_(MSG_CHOOSEFILE),
  1607.         ASLFR_Flags1, FRF_DOPATTERNS,
  1608.         ASLFR_InitialPattern, (ULONG)((AslBase->lib_Version < 38)?
  1609.             "YPQ~(#?.info)" : "YPQ#?"),
  1610.         ASLFR_RejectIcons, TRUE,
  1611.         TAG_DONE);
  1612.  
  1613.     /*- get number of next year -*/
  1614.     CalcYear_(TRUE, 0);
  1615.  
  1616.     /*- read icon's tool types or bundled file -*/
  1617.     ReadToolTypes_(wbarg);
  1618.  
  1619.     /*- wait for and process messages -*/
  1620.     do
  1621.     {    do
  1622.         {    Wait(signals);
  1623.  
  1624.             /* process application messages */
  1625.             ProcessAppMessages_();
  1626.  
  1627.             /* process window messages */
  1628.             flag= ProcessWindowMessages_();
  1629.         } while (!flag);
  1630.  
  1631.         /* calendar printing requested */
  1632.         if (flag&REQPRINT)
  1633.         {    static struct TagItem abletag[]=
  1634.             {    GA_Disabled, FALSE,
  1635.                 TAG_DONE
  1636.             };
  1637.             struct Gadget *gad;
  1638.             
  1639.             /* disable gadgets */
  1640.             GT_SetGadgetAttrsA(gads[GID_STOP].gad, win, NULL, abletag);
  1641.             abletag[0].ti_Data= TRUE;
  1642.             gad= gads[0].gad;
  1643.             do
  1644.             {    if (gad == gads[GID_FREQ].gad)
  1645.                     OffGadget(gad, win, NULL);
  1646.                 else
  1647.                     GT_SetGadgetAttrsA(gad, win, NULL, abletag);
  1648.             } while ((gad= gad->NextGadget) != gads[GID_STOP].gad);
  1649.  
  1650.             /* print calendar, increment quarter and year */
  1651.             if (!PrintCalendar_(gads[GID_QUART].contents,
  1652.                 gads[GID_PITCH].contents, gads[GID_GRAPH].contents))
  1653.             {    if (gads[GID_QUART].contents != 4)
  1654.                     GT_SetGadgetAttrs(gads[GID_QUART].gad, win, NULL,
  1655.                         GTCY_Active, gads[GID_QUART].contents=
  1656.                             (gads[GID_QUART].contents+1)&3,
  1657.                         TAG_DONE);
  1658.                 if (!(gads[GID_QUART].contents&3))
  1659.                     CalcYear_(FALSE, (year == 2199)? 1582 : year+1);
  1660.             }
  1661.  
  1662.             /* re-enable gadgets */
  1663.             GT_SetGadgetAttrsA(gads[GID_STOP].gad, win, NULL, abletag);
  1664.             abletag[0].ti_Data= FALSE;
  1665.             gad= gads[GID_QUART].gad;
  1666.             do
  1667.             {    if (gad == gads[GID_FREQ].gad)
  1668.                 {    UWORD x= gad->LeftEdge;
  1669.                     UWORD y= gad->TopEdge;
  1670.  
  1671.                     SetDrMd(win->RPort, JAM1);
  1672.                     SetAPen(win->RPort, 0);
  1673.                     RectFill(win->RPort, x, y,
  1674.                         x+gad->Width-1, y+gad->Height-1);
  1675.                     DrawBevelBox(win->RPort, x, y, gad->Width, gad->Height,
  1676.                         GT_VisualInfo, (ULONG)vi,
  1677.                         TAG_DONE);
  1678.                     OnGadget(gad, win, NULL);
  1679.                 } else
  1680.                     GT_SetGadgetAttrsA(gad, win, NULL, abletag);
  1681.             } while ((gad= gad->NextGadget) != gads[GID_STOP].gad);
  1682.         }
  1683.     } while (!(flag&REQEXIT));
  1684.  
  1685.     return RETURN_OK;
  1686. }
  1687.  
  1688. /*==== clean up all at exit ====*/
  1689. void CleanUp_(void)
  1690. {    ClosePrinter_();
  1691.     if (!cli)
  1692.     {    if (appwin) RemoveAppWindow(appwin);
  1693.         if (appport)
  1694.         {    struct Message *msg;
  1695.  
  1696.             while (msg= GetMsg(appport)) ReplyMsg(msg);
  1697.             DeleteMsgPort(appport);
  1698.         }
  1699.         if (freq) FreeAslRequest((APTR)freq);
  1700.         if (win) CloseWindow(win);
  1701.         if (frimage.ImageData != fridata)
  1702.             FreeMem(&frimage.ImageData[-1], frimage.ImageData[-1]);
  1703.         if (pimage) FreeMem(pimage, sizeof(mouseimage));
  1704.         if (congad) FreeGadgets(congad);
  1705.         if (lock != ~0) CurrentDir(lock);
  1706.         if (vi) FreeVisualInfo(vi);
  1707.         if (pubscr) UnlockPubScreen(NULL, pubscr);
  1708.  
  1709.         if (AslBase) CloseLibrary(AslBase);
  1710.         if (GadToolsBase) CloseLibrary(GadToolsBase);
  1711.         if (GfxBase) CloseLibrary(GfxBase);
  1712.         if (WorkbenchBase) CloseLibrary(WorkbenchBase);
  1713.     }
  1714.  
  1715.     if (LocaleBase)
  1716.     {    CloseCatalog(cat);
  1717.         CloseLocale(locale);
  1718.         CloseLibrary(LocaleBase);
  1719.     }
  1720.     if (IconBase) CloseLibrary(IconBase);
  1721.     if (UtilityBase) CloseLibrary(UtilityBase);
  1722.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  1723. }
  1724.  
  1725. /*==== main program ====*/
  1726. int main(int argc, TEXT *argv[])
  1727. /* ATTENTION: argv isn't set if called from CLI in Aztec-C */
  1728. {    static LONG argray[8]=    /* argument array */
  1729.      { 0, 0, 0, 0, 0, 0, 0, DEFGRAPH };
  1730.     BYTE num;                /* number of error message */
  1731.     UBYTE pitch;            /* self-explaining */
  1732.  
  1733.     /*- only allow AmigaOS 2.04 and up -*/
  1734.     if (SysBase->lib_Version < 37)
  1735.     {    BPTR file;
  1736.         if (argc) file= Output();
  1737.         else      file= Open("CON:0/0/350/30/" PRGNAME, MODE_NEWFILE);
  1738.         Write(file, "Sorry, you'll need at least AmigaOS 2.04!\n", 42);
  1739.         Delay(100);
  1740.         Close(file);
  1741.         return RETURN_FAIL;
  1742.     }
  1743.  
  1744.     /*- open libraries -*/
  1745.     IntuitionBase= OpenLibraryQ_("intuition.library");
  1746.     if (LocaleBase= OpenLibrary("locale.library", 38))
  1747.     {    locale= OpenLocale(NULL);
  1748.         cat= OpenCatalogA(locale, PRGNAME ".catalog", NULL);
  1749.     }
  1750.     UtilityBase= OpenLibraryQ_("utility.library");
  1751.  
  1752.     /*- set cleanup routine -*/
  1753.     atexit(CleanUp_);
  1754.  
  1755.     /*- debugging feature: start GUI from CLI -*/
  1756.     #ifdef DEBUG
  1757.     if (argc)
  1758.     {    struct WBStartup wbstartup;
  1759.         struct WBArg wbarg;
  1760.         BPTR lock;
  1761.         int rc;
  1762.  
  1763.         wbstartup.sm_NumArgs= 1;
  1764.         wbstartup.sm_ArgList= &wbarg;
  1765.         lock= CurrentDir((BPTR)0);
  1766.         wbarg.wa_Lock= DupLock(lock);
  1767.         CurrentDir(lock);
  1768.         wbarg.wa_Name= PRGNAME;
  1769.         argv= (TEXT **)&wbstartup;
  1770.         argc= 0;
  1771.     }
  1772.     #endif
  1773.  
  1774.     /*- jump to GUI main routine -*/
  1775.     if (!argc) return guimain((struct WBStartup *)argv);
  1776.  
  1777.     /*- set CLI flag, print copyright message -*/
  1778.     cli= TRUE;
  1779.     Printf("*** " PRGNAME " *** " VERSION " - (c)1991 by Dieter Temme\n",
  1780.         (ULONG)NULL, (ULONG)NULL);
  1781.  
  1782.     /*- read parameters -*/
  1783.     FreeArgs(ReadArgs("File/A,Year/N,Quarter/N,"
  1784.         "PICA/S,ELITE/S,SEMI/S,FINE/S,IBMPC/S", (TEXT **)argray, NULL));
  1785.  
  1786.     /*- read pitch -*/
  1787.     {    UBYTE i;
  1788.  
  1789.         for (pitch= 0; pitch <= 3; pitch++) if (argray[pitch+3]) break;
  1790.         for (i= pitch+1; i <= 3; i++) if (argray[i+3])
  1791.         {    PrintError_(0, GetCatalogStrQ_(MSG_PITCHERR));
  1792.             return RETURN_FAIL;
  1793.         }
  1794.     }
  1795.  
  1796.     /*- read quarter -*/
  1797.     if (argray[2] && (*(ULONG *)argray[2] > 3))
  1798.     {    PrintError_(0, GetCatalogStrQ_(MSG_QUARTERR));
  1799.         return RETURN_FAIL;
  1800.     }
  1801.  
  1802.     /*- read filename and file and create filedays -*/
  1803.     if (!ReadFile_((TEXT *)argray[7])) return RETURN_FAIL;
  1804.  
  1805.     /*- read number of year and create yeardays -*/
  1806.     if (!CalcYear_(!argray[1], argray[1]))
  1807.     {    PrintError_(0, GetCatalogStrQ_(MSG_YEARERR));
  1808.         return RETURN_FAIL;
  1809.     }
  1810.  
  1811.     /*- print calendar and exit -*/
  1812.     return PrintCalendar_(argray[2]? (UBYTE)*(ULONG *)argray[2] : 0,
  1813.         pitch, argray[7]);
  1814. }
  1815.  
  1816. #ifdef _DCC
  1817. int wbmain(struct WBStartup *wbstart)
  1818. {    return main(0, (TEXT **)wbstart);
  1819. }
  1820. #endif
  1821.